package com.sclimin.pickerview;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.BoringLayout;
import android.text.Layout;
import android.text.TextPaint;
import android.text.TextUtils;

/**
 * 作者：limin
 * <p>
 * 创建时间：2019/1/24
 */
final class RollerItem {

    /**
     * 是否重新计算
     */
    private boolean mShouldCompute = true;
    private String mText = "";
    private RollerView.Ellipsize mEllipsize;

    // 文字超出处理
    private final TextDrawHelper mTextDrawHelper = new TextDrawHelper();

    /**
     * 设置文字内容
     * @param text 文字内容
     */
    void setText(String text) {
        if (text == null) {
            text = "";
        }

        if (!text.equals(mText)) {
            mText = text;
            postShouldCompute();
        }
    }

    /**
     * 文字超出显示模式
     * @param ellipsize 超出显示位置
     * @see com.sclimin.pickerview.RollerView.Ellipsize
     */
    void setEllipsize(RollerView.Ellipsize ellipsize) {
        if (mEllipsize != ellipsize) {
            mEllipsize = ellipsize;
            postShouldCompute();
        }
    }

    /**
     * 需要重新计算
     */
    void postShouldCompute() {
        mShouldCompute = true;
    }

    /**
     * 计算文字超出
     * @param paint 绘制文字Paint
     * @param width 允许的最大显示宽度
     */
    void compute(TextPaint paint, int width) {
        if (mShouldCompute) {
            final TextUtils.TruncateAt ellipsize = mEllipsize == null ?
                    TextUtils.TruncateAt.END : mEllipsize.value;

            mTextDrawHelper.compute(mText, paint, ellipsize, width);

            mShouldCompute = false;
        }
    }

    void draw(Canvas canvas, int textColor, float width,
              RollerView.Alignment textAlignment, boolean isRTL) {
        if (!mShouldCompute) {
            mTextDrawHelper.draw(canvas, textColor, width, textAlignment, isRTL);
        }
    }

    private static Paint.FontMetrics fontMetricsFrom(TextPaint paint,
                                                     Paint.FontMetrics fontMetrics) {
        if (fontMetrics == null) {
            fontMetrics = new Paint.FontMetrics();
        }
        paint.getFontMetrics(fontMetrics);
        return fontMetrics;
    }

    /**
     *
     * @param fontMetrics 字体信息
     * @param paint 文字绘制Paint
     * @param text 需绘制的文本
     * @param boringMetrics 单行文字绘制信息
     * @return 单行文字信息
     */
    private static BoringLayout.Metrics boringMetricsFrom(Paint.FontMetrics fontMetrics,
                                          TextPaint paint,
                                          String text,
                                          BoringLayout.Metrics boringMetrics) {
        if (boringMetrics == null) {
            boringMetrics = new BoringLayout.Metrics();
        }
        boringMetrics.ascent = (int) fontMetrics.ascent;
        boringMetrics.top = (int) fontMetrics.top;
        boringMetrics.descent = (int) fontMetrics.descent;
        boringMetrics.bottom = (int) fontMetrics.bottom;
        boringMetrics.leading = (int) fontMetrics.leading;
        boringMetrics.width = (int) paint.measureText(text);

        return boringMetrics;
    }

    private static BoringLayout layoutFrom(TextPaint paint,
                                           String text,
                                           BoringLayout.Metrics boringMetrics,
                                           TextUtils.TruncateAt ellipsize,
                                           int width,
                                           BoringLayout layout) {
        if (layout == null) {
            layout = BoringLayout.make(text, paint, width, Layout.Alignment.ALIGN_NORMAL,
                    1, 0, boringMetrics, true, ellipsize, width);
        }
        else {
            layout.replaceOrMake(text, paint, width, Layout.Alignment.ALIGN_NORMAL,
                    1, 0, boringMetrics, true, ellipsize, width);
        }
        return layout;
    }

    static class TextDrawHelper {
        private final TextPaint mPaint = new TextPaint();

        private BoringLayout mLayout;
        private BoringLayout.Metrics mBoringMetrics;
        private Paint.FontMetrics mFontMetrics;

        boolean setEllipsize(RollerView.Ellipsize ellipsize) {
            return false;
        }

        void compute(String text, TextPaint paint,
                     TextUtils.TruncateAt ellipsize, int width) {
            compute(text, paint, 1, ellipsize, width);
        }

        void compute(String text, TextPaint paint, float textSizeScale,
                     TextUtils.TruncateAt ellipsize, int width) {
            mPaint.set(paint);
            mPaint.setTextSize(paint.getTextSize() * textSizeScale);

            // 取出字体信息
            mFontMetrics = fontMetricsFrom(paint, mFontMetrics);
            mBoringMetrics = boringMetricsFrom(mFontMetrics, mPaint, text, mBoringMetrics);
            mLayout = layoutFrom(mPaint, text, mBoringMetrics, ellipsize, width, mLayout);
        }

        void draw(Canvas canvas, int textColor, float width, RollerView.Alignment textAlignment, boolean isRTL) {
            if (mLayout != null) {
                canvas.save();
                TextPaint paint = mLayout.getPaint();
                paint.setColor(textColor);
                paint.setTextAlign(Paint.Align.LEFT);

                if (textAlignment == RollerView.Alignment.START) {
                    if (isRTL) {
                        paint.setTextAlign(Paint.Align.RIGHT);
                        canvas.translate(width, 0);
                    }
                    else {
                        paint.setTextAlign(Paint.Align.LEFT);
                    }
                }
                else if (textAlignment == RollerView.Alignment.END) {
                    if (isRTL) {
                        paint.setTextAlign(Paint.Align.LEFT);
                    }
                    else {
                        paint.setTextAlign(Paint.Align.RIGHT);
                        canvas.translate(width, 0);
                    }
                }
                else {
                    paint.setTextAlign(Paint.Align.CENTER);
                    canvas.translate(width * 0.5f, 0);
                }
                mLayout.draw(canvas);
                canvas.restore();
            }
        }
    }
}
